package igor.lakienko.ru.generation.quotes.service;

import igor.lakienko.ru.generation.quotes.dto.CryptocurrencyDto;
import igor.lakienko.ru.generation.quotes.dto.MessageEventDto;
import igor.lakienko.ru.generation.quotes.entity.CryptocurrencyEntity;
import igor.lakienko.ru.generation.quotes.enums.Cryptocurrency;
import igor.lakienko.ru.generation.quotes.enums.RecommendationAnalysts;
import igor.lakienko.ru.generation.quotes.enums.TypeSecurities;
import igor.lakienko.ru.generation.quotes.mapper.CryptocurrencyMapper;
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.BDDMockito.given;

@ExtendWith(MockitoExtension.class)
class CryptocurrencyServiceTest {

    @Mock
    CryptocurrencyMapper cryptocurrencyMapper;

    @InjectMocks
    CryptocurrencyService cryptocurrencyService;

    @BeforeEach
    void setUp() {
        getSizeBatchField();
    }

    @Test
    void whenGetCryptocurrency_thenSuccessRandomCryptocurrencyDto() {
        //given
        CryptocurrencyDto cryptocurrencyDefault = getCryptocurrencyDefault();
        given(cryptocurrencyMapper.cryptocurrencyEntityToDto(any(CryptocurrencyEntity.class)))
                .willReturn(cryptocurrencyDefault);

        //when
        MessageEventDto cryptocurrency = cryptocurrencyService.getCryptocurrency();

        //then
        assertThat(cryptocurrency).isEqualTo(cryptocurrencyDefault);
    }

    @Test
    void whenGetCryptocurrencies_thenSuccessRandomCryptocurrencyDtos() {
        //given
        List<CryptocurrencyDto> cryptocurrencyDefault = List.of(getCryptocurrencyDefault());
        given(cryptocurrencyMapper.cryptocurrenciesEntityToDto(anyList())).willReturn(cryptocurrencyDefault);

        //when
        Collection<CryptocurrencyDto> cryptocurrencyDtos = cryptocurrencyService.getCryptocurrencies();

        //then
        assertThat(cryptocurrencyDtos).isEqualTo(cryptocurrencyDefault);
    }

    @SneakyThrows
    private void getSizeBatchField() {
        Field quoteSizeBatch = cryptocurrencyService.getClass().getDeclaredField("cryptocurrencySizeBatch");
        quoteSizeBatch.setAccessible(true);
        quoteSizeBatch.set(cryptocurrencyService, 2);
    }

    private CryptocurrencyDto getCryptocurrencyDefault() {
        return CryptocurrencyDto.builder()
                .id(UUID.randomUUID().toString())
                .sentAt(ZonedDateTime.now())
                .type(TypeSecurities.STOCK)
                .cryptocurrency(Cryptocurrency.BTC_RUB)
                .bid(BigDecimal.ONE)
                .offer(BigDecimal.TEN)
                .fullCryptocurrencyName(Cryptocurrency.BTC_RUB.getDescription())
                .price(1_000.00F)
                .recommendationAnalysts(RecommendationAnalysts.SELL.getRecommendation())
                .monthlyVolatility(5.00F)
                .build();
    }
}